package cn.lyjuan.pojoutils.template.impl;

import cn.lyjuan.pojoutils.bean.ColumnBean;
import cn.lyjuan.pojoutils.bean.TableBean;
import cn.lyjuan.pojoutils.template.IMapperXMLTemplate;
import cn.lyjuan.pojoutils.util.PojoUtils;

import java.util.List;

/**
 * Created by ly on 2014/11/21.
 */
public class AMapperXMLTemplate implements IMapperXMLTemplate
{
    @Override
    public String genMapperXml(TableBean tableBean, List<ColumnBean> cols)
    {
        StringBuilder sb = new StringBuilder()
        .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
        .append("<!DOCTYPE mapper PUBLIC\n")
        .append("        \"-//mybatis.org//DTD Mapper 3.0//EN\"\n")
        .append("        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n")
        .append("<mapper namespace=\"").append(tableBean.getMapperPkgName()).append(".").append(tableBean.getMapperName()).append("\">\n\n");

        // 查询SQL
        String[] xmlSelect = genSelect(tableBean, cols);
        // 添加SQL
        String[] xmlInsert = genInsert(tableBean, cols);
        // 更新SQL
        String[] xmlUpdate = genUpdate(tableBean, cols);
        // 删除SQL
        String[] xmlDelete = genDelete(tableBean, cols);

        sb.append(xmlSelect[0]).append("\n\n").append(xmlInsert[0]).append("\n\n").append(xmlUpdate[0]).append("\n\n").append(xmlDelete[0]).append("\n\n")
        .append(xmlSelect[1]).append("\n\n").append(xmlInsert[1]).append("\n\n").append(xmlUpdate[1]).append("\n\n").append(xmlDelete[1]).append("\n\n")
        .append("\n</mapper>");

        return sb.toString();
    }

    @Override
    public String[] genSelect(TableBean tableBean, List<ColumnBean> cols)
    {
        // 副 XML SELECT 部分
        StringBuilder xmlSql = new StringBuilder()
        // baseResultMap
        .append("\t<!-- POJO映射 -->\n")
        .append("\t<resultMap id=\"baseResultMap\" type=\"").append(tableBean.getPojoPkgName() + "." + tableBean.getPojoName() + "\">\n");
        for (ColumnBean c : cols)
        {
            if (c.isPriKey)
                xmlSql.append("\t\t<id property=\"" + c.column + "\" column=\"").append(tableBean.getTableName() + "_").append(c.column).append("\" />\n");
            else
                xmlSql.append("\t\t<result property=\"" + c.column + "\" column=\"").append(tableBean.getTableName() + "_").append(c.column)
                .append("\" javaType=\"" + c.mybatisJavaType + "\" jdbcType=\"" + c.mybatisJdbcType + "\" />\n");
        }

        xmlSql.append("\t</resultMap>\n\n\n");

        // selectName
        xmlSql.append("\t<!-- 查询条件 -->\n")
        .append("\t<sql id=\"selectName\">\n")
        .append("\t\t<trim suffixOverrides=\",\">\n");
        for (ColumnBean c : cols)
            xmlSql.append("\t\t\t" + tableBean.getTableName() + "." + c.column + " " + tableBean.getTableName() + "_" + c.column + ",\n");
        xmlSql.append("\t\t</trim>\n\t</sql>\n\n\n");

        // selectWhere
        xmlSql.append("\t<!-- 基本 where 条件 SQL 语句 -->\n")
        .append("\t<sql id=\"selectWhere\">\n")
        .append("\t\t<where>\n");
        String invalidVal = "null";
        for (ColumnBean c : cols)
        {
            xmlSql.append("\t\t\t<if test=\"null != ").append(tableBean.getObjName());

            // 数值
            if (PojoUtils.isTypeNum(c.typeName))
                invalidVal = tableBean.getNumberInvalidVal();
            else
                invalidVal = "null";

            xmlSql.append(" and ").append(invalidVal).append(" != ").append(tableBean.getObjName() + "." + c.column);
            if (PojoUtils.isTypeString(c.typeName))
                xmlSql.append(" and '' != ").append(tableBean.getObjName() + "." + c.column);
            xmlSql.append("\" > and ").append(tableBean.getTableName().toLowerCase() + "." + c.column)
                .append(" = #{").append(tableBean.getObjName() + "." + c.column).append("} </if>\n");
        }
        xmlSql.append("\t\t</where>\n")
        .append("\t</sql>\n");

        // 主 XML SELECT 部分
        StringBuilder selectSql = new StringBuilder();

        selectSql.append("\t<!-- 查询 -->\n")
        .append("\t<select id=\"select\" resultMap=\"baseResultMap\">\n")
        .append("\t\tSELECT\n")
        .append("\t\t\t<include refid=\"selectName\" />\n")
        .append("\t\tFROM\n")
        .append("\t\t\t").append(tableBean.getTableName()).append(" ").append(tableBean.getTableName().toLowerCase()).append("\n")
        .append("\t\t<include refid=\"selectWhere\" />\n")
        .append("\t</select>\n\n\n");
        for (ColumnBean c : cols)
        {
            if (c.isPriKey)
            {
                selectSql.append("\t<!-- 主键查询 -->\n")
                .append("\t<select id=\"selectBy").append(PojoUtils.firstUpLowCase(c.column, true)).append("\" resultMap=\"baseResultMap\">\n")
                .append("\t\tSELECT\n")
                .append("\t\t\t<include refid=\"selectName\" />\n")
                .append("\t\tFROM\n")
                .append("\t\t\t").append(tableBean.getTableName()).append(" ").append(tableBean.getTableName().toLowerCase()).append("\n")
                .append("\t\tWHERE\n")
                .append("\t\t\t").append(tableBean.getTableName().toLowerCase()).append(".").append(c.column).append(" = #{").append(c.column).append("}\n")
                .append("\t</select>\n\n\n");
                break;
            }
        }
        selectSql.append("\t<!-- 查询列表 -->\n")
        .append("\t<select id=\"selects\" resultMap=\"baseResultMap\">\n")
        .append("\t\tSELECT\n")
        .append("\t\t\t<include refid=\"selectName\" />\n")
        .append("\t\tFROM ").append(tableBean.getTableName()).append(" ").append(tableBean.getTableName().toLowerCase()).append("\n")
        .append("\t\t<include refid=\"selectWhere\" />\n")
        .append("\t</select>\n\n\n")
        .append("\t<!-- 查询分页 -->\n")
        .append("\t<select id=\"selectForPage\" resultMap=\"baseResultMap\">\n")
        .append("\t\tSELECT\n")
        .append("\t\t\t<include refid=\"selectName\" />\n")
        .append("\t\tFROM ").append(tableBean.getTableName()).append(" ").append(tableBean.getTableName().toLowerCase()).append("\n")
        .append("\t\t<include refid=\"selectWhere\" />\n")
        .append("\t\tLIMIT #{start}, #{len}\n")
        .append("\t</select>\n");

        return new String[]{xmlSql.toString(), selectSql.toString()};
    }

    @Override
    public String[] genInsert(TableBean tableBean, List<ColumnBean> cols)
    {
        // 副 XML INSERT 部分
        StringBuilder xmlSql = new StringBuilder()
        // insertName
        .append("\t<!-- 新增 SQL 字段名称 -->\n")
        .append("\t<sql id=\"insertName\" >\n")
        .append("\t\t<trim prefix=\"(\" suffixOverrides=\",\" suffix=\")\" >\n");
        String invalidVal = "null";
        for (ColumnBean c : cols)
        {
            if (PojoUtils.isTypeNum(c.typeName))
                invalidVal = tableBean.getNumberInvalidVal();
            else
                invalidVal = "null";

            xmlSql.append("\t\t\t<if test=\"null != ").append(tableBean.getObjName()).append(" and ")
                    .append(invalidVal).append(" != ").append(tableBean.getObjName() + "." + c.column);
            if (PojoUtils.isTypeString(c.typeName))
                xmlSql.append(" and '' != ").append(tableBean.getObjName() + "." + c.column);
            xmlSql.append("\">").append(c.column).append(",</if>\n");
        }
        xmlSql.append("\t\t</trim>\n")
        .append("\t</sql>\n\n\n");
        // insertValue
        xmlSql.append("\t<!-- 新增 SQL 字段值 -->\n")
        .append("\t<sql id=\"insertValue\" >\n")
        .append("\t\t<trim prefix=\"(\" suffixOverrides=\",\" suffix=\")\" >\n");
        for (ColumnBean c : cols)
        {
            if (PojoUtils.isTypeNum(c.typeName))
                invalidVal = tableBean.getNumberInvalidVal();
            else
                invalidVal = "null";
            xmlSql.append("\t\t\t<if test=\"null != ").append(tableBean.getObjName()).append(" and ")
            .append(invalidVal).append(" != ").append(tableBean.getObjName() + "." + c.column);
            if (PojoUtils.isTypeString(c.typeName))
                xmlSql.append(" and '' != ").append(tableBean.getObjName() + "." + c.column);
            xmlSql.append("\">#{")
            .append(tableBean.getObjName() + "." + c.column).append(", jdbcType=").append(c.mybatisJdbcType).append("},</if>\n");
        }
        xmlSql.append("\t\t</trim>\n\t</sql>\n");

        // 主 XML INSERT 部分
        StringBuilder insertSql = new StringBuilder();
        insertSql.append("\t<!-- 增加，MySQL中，如果新增时指定了 主键 值，则主键的自动增长不起作用 -->\n")
        .append("\t<insert id=\"insert\"");
        for (ColumnBean c : cols)
        {
            if (c.isPriKey && c.autoInc)
            {
                insertSql.append(" useGeneratedKeys=\"true\" keyColumn=\"").append(c.column)
                .append("\" keyProperty=\"").append(tableBean.getObjName() + "." + c.column).append("\"");
                break;
            }
        }
        insertSql.append(">\n")
                .append("\t\tINSERT INTO ").append(tableBean.getTableName()).append("\n")
        .append("\t\t\t<include refid=\"insertName\" />\n")
                .append("\t\tVALUES <include refid=\"insertValue\" />\n")
        .append("\t</insert>\n");

        return new String[]{xmlSql.toString(), insertSql.toString()};
    }

    @Override
    public String[] genUpdate(TableBean tableBean, List<ColumnBean> cols)
    {
        // 副 XML SQL 部分
        StringBuilder xmlSql = new StringBuilder()
        // updateSet
        .append("\t<!-- 更新 SQL SET 语句 -->\n")
        .append("\t<sql id=\"updateSet\" >\n")
        .append("\t\t<set>\n");
        String invalidVal = "null";
        for (ColumnBean c : cols)
        {
            if (PojoUtils.isTypeNum(c.typeName))  invalidVal = tableBean.getNumberInvalidVal();
            else invalidVal = "null";
            xmlSql.append("\t\t\t<if test=\"null != ").append(tableBean.getObjName()).append(" and ")
            .append(invalidVal).append(" != ").append(tableBean.getObjName() + "." + c.column);
            if (PojoUtils.isTypeString(c.typeName))
                xmlSql.append(" and '' != ").append(tableBean.getObjName() + "." + c.column);
            xmlSql.append(" \">")
            .append(c.column).append(" = #{").append(tableBean.getObjName() + "." + c.column)
            .append(", jdbcType=").append(c.mybatisJdbcType).append("},</if>\n");
        }
        xmlSql.append("\t\t</set>\n")
        .append("\t</sql>\n");

        // 副 XML UPDATE 部分
        StringBuilder updateSql = new StringBuilder();
        // updateBy{主键}
        for (ColumnBean c : cols)
        {
            if (c.isPriKey)
            {
                updateSql.append("\t<!-- 更新 -->\n")
                .append("\t<update id=\"updateBy").append(PojoUtils.firstUpLowCase(c.column, true)).append("\">\n")
                .append("\t\tUPDATE ").append(tableBean.getTableName()).append("\n")
                .append("\t\t\t<include refid=\"updateSet\"/>\n")
                .append("\t\tWHERE\n")
                .append("\t\t\t").append(c.column).append(" = #{").append(tableBean.getObjName() + "." + c.column).append("}\n")
                .append("\t</update>\n");
                break;
            }
        }

        return new String[]{xmlSql.toString(), updateSql.toString()};
    }

    @Override
    public String[] genDelete(TableBean tableBean, List<ColumnBean> cols)
    {
        // 主 XML DELETE 部分
        StringBuilder deleteSql = new StringBuilder();
        for (ColumnBean c : cols)
        {
            if (c.isPriKey)
            {
                deleteSql.append("\t<!-- 主键删除 -->\n")
                .append("\t<delete id=\"deleteBy").append(PojoUtils.firstUpLowCase(c.column, true)).append("\" >\n")
                .append("\t\tDELETE FROM ").append(tableBean.getTableName()).append("\n")
                .append("\t\tWHERE ").append(c.column).append(" = #{").append(c.column).append("}\n")
                .append("\t</delete>\n")
                .append("\n");
                break;
            }
        }

        /**
         * @Modify by Chad@2016-03-08
         * @Desc 去掉SQL语句关联数据库名称
         */
//        deleteSql.append("\t<!-- POJO 删除 -->\n")
//        .append("\t<delete id=\"delete\" >\n")
//        .append("\t\tDELETE ").append(tableBean.getTableName().toLowerCase()).append(" FROM ")
//        .append(tableBean.getDatabase()).append(".").append(tableBean.getTableName().toLowerCase())
//        .append(" ").append(tableBean.getTableName().toLowerCase()).append("\n")
//        .append("\t\t<include refid=\"selectWhere\" />\n")
//        .append("\t</delete>\n");

        return new String[]{"", deleteSql.toString()};
    }
}
